<template>
  <div>
    <el-dialog
      v-model="dialogVisible"
      :title="'设备权限分配'"
      width="1300px"
      append-to-body
      @close="handleClose"
    >
    <el-row>
      <el-col :span="24">
        <!-- 添加已关联设备搜索表单 -->
        <el-form
          class="-mb-15px"
          :model="deviceQueryParams"
          ref="deviceQueryFormRef"
          :inline="true"
          label-width="100px"
        >
          <el-form-item label="设备类型" prop="deviceType">
            <el-select
              v-model="deviceQueryParams.deviceType"
              placeholder="请选择设备类型"
              clearable
              class="!w-240px"
            >
              <el-option
                v-for="dict in getIntDictOptions(DICT_TYPE.MQTT_DEVICE_TYPE)"
                :key="dict.value"
                :label="dict.label"
                :value="dict.value"
              />
            </el-select>
          </el-form-item>
          <el-form-item label="设备名称" prop="deviceName">
            <el-input
              v-model="deviceQueryParams.deviceName"
              placeholder="请输入设备名称"
              clearable
              @keyup.enter="handleDeviceQuery"
              class="!w-240px"
            />
          </el-form-item>
          <el-form-item>
            <el-button @click="handleDeviceQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
            <el-button @click="resetDeviceQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
          </el-form-item>
          <el-form-item>
            <el-button type="primary" @click="handleAddDevice">关联设备</el-button>
            <el-button type="danger" @click="handleBatchRemove" :disabled="!hasSelectedDevices">批量移除</el-button>
            <el-button @click="loadAssignedDevices"><Icon icon="ep:refresh" class="mr-5px" /> 刷新</el-button>
            <el-button type="danger" @click="handleClose"><Icon icon="ep:close" class="mr-5px" /> 关闭</el-button>
          </el-form-item>
        </el-form>
        
        <!-- 已关联设备表格 - 修改数据源为paginatedAssignedDeviceList -->
        <el-table
          ref="deviceTableRef"
          v-loading="loading"
          :data="paginatedAssignedDeviceList"
          :stripe="true"
          :show-overflow-tooltip="true"
          height="400px"
          row-key="id"
          @selection-change="handleDeviceSelectionChange"
        >
          <el-table-column type="selection" width="55" />
          <el-table-column label="设备类型" align="left" prop="deviceType" width="80" fixed="left">
            <template #default="scope">
              <dict-tag :type="DICT_TYPE.MQTT_DEVICE_TYPE" :value="scope.row.deviceType" />
            </template>
          </el-table-column>
          <el-table-column label="设备名称" prop="deviceName" width="160" fixed="left" />
          <el-table-column label="设备在线" align="center" prop="state">
            <template #default="scope">
              <dict-tag :type="DICT_TYPE.IOT_DEVICE_STATE" :value="scope.row.isOnline" />
            </template>
          </el-table-column>
          <el-table-column label="网关SN编号" align="left" prop="gatewayId" width="120" />
          <el-table-column label="设备地址" align="left" prop="address" width="200" />
          <el-table-column label="设备图片" align="center" prop="picUrl" width="100">
            <template #default="scope">
              <el-image
                :src="uploadUrl + scope.row.picUrl || defaultImage"
                fit="cover"
                class="device-image"
              />
            </template>
          </el-table-column>
          <el-table-column label="物联网卡号(ICCID)" align="left" prop="firmwareId" width="190" />
          <el-table-column label="设备唯一码" align="left" prop="deviceKey" width="120" />
          <el-table-column
            label="创建时间"
            align="left"
            prop="createTime"
            :formatter="dateFormatter"
            width="180px"
          />
          <el-table-column label="操作" align="center" fixed="right" width="80">
            <template #default="scope">
              <el-button size="small" type="danger" @click="handleRemoveDevice(scope.row.id)">移除</el-button>
            </template>
          </el-table-column>
        </el-table>

        <!-- 操作按钮区域 -->
        <div class="table-footer" style="margin-top: 10px; display: flex; justify-content: space-between; align-items: center;">
          <!-- 已关联设备分页组件 -->
          <Pagination
            v-model:page="devicePagination.pageNo"
            v-model:limit="devicePagination.pageSize"
            :total="filteredAssignedDeviceList.length"
            @pagination="handleDevicePagination"
          />
        </div>
      </el-col>
    </el-row>
  </el-dialog>
  
  <!-- 新增设备对话框 -->
  <el-dialog
    v-model="addDeviceDialogVisible"
    :title="'新增关联设备'"
    width="1500px"
    append-to-body
  >
    <el-row>
      <el-col :span="24">
        <!-- 设备搜索表单 -->
        <el-form
          class="-mb-15px"
          :model="addDeviceQueryParams"
          ref="addDeviceQueryFormRef"
          :inline="true"
          label-width="100px"
        >
          <el-form-item label="设备类型" prop="deviceType">
            <el-select
              v-model="addDeviceQueryParams.deviceType"
              placeholder="请选择设备类型"
              clearable
              class="!w-240px"
            >
              <el-option
                v-for="dict in getIntDictOptions(DICT_TYPE.MQTT_DEVICE_TYPE)"
                :key="dict.value"
                :label="dict.label"
                :value="dict.value"
              />
            </el-select>
          </el-form-item>
          <el-form-item label="设备名称" prop="deviceName">
            <el-input
              v-model="addDeviceQueryParams.deviceName"
              placeholder="请输入设备名称"
              clearable
              @keyup.enter="handleAddDeviceQuery"
              class="!w-240px"
            />
          </el-form-item>

            <el-form-item>
              <el-button @click="handleAddDeviceQuery"
                ><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button
              >
              <el-button @click="resetAddDeviceQuery"
                ><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button
              >
            </el-form-item>
          </el-form>

          <!-- 设备选择表格 -->
          <el-table
            ref="addDeviceTableRef"
            v-loading="addDeviceLoading"
            :data="addDeviceList"
            :stripe="true"
            :show-overflow-tooltip="true"
            height="350px"
            row-key="id"
            @selection-change="handleAddDeviceSelectionChange"
          >
            <el-table-column type="selection" label="编号" prop="id" fixed="left" width="80" />
            <el-table-column
              label="设备类型"
              align="left"
              prop="deviceType"
              width="80"
              fixed="left"
            >
              <template #default="scope">
                <dict-tag :type="DICT_TYPE.MQTT_DEVICE_TYPE" :value="scope.row.deviceType" />
              </template>
            </el-table-column>
            <el-table-column label="设备名称" prop="deviceName" fixed="left" />
            <el-table-column label="设备在线" align="center" width="120" prop="state">
              <template #default="scope">
                <dict-tag :type="DICT_TYPE.IOT_DEVICE_STATE" :value="scope.row.isOnline" />
              </template>
            </el-table-column>
            <el-table-column label="网关SN编号" align="left" prop="gatewayId" width="120" />
            <el-table-column label="设备地址" align="left" prop="address" width="200" />
            <el-table-column label="设备图片" align="center" prop="picUrl" width="100">
              <template #default="scope">
                <el-image
                  :src="uploadUrl + scope.row.picUrl || defaultImage"
                  fit="cover"
                  class="device-image"
                />
              </template>
            </el-table-column>
            <!-- <el-table-column label="物联网卡号(ICCID)" align="left" prop="firmwareId" width="190" /> -->
            <el-table-column label="设备唯一码" align="left" prop="deviceKey" width="120" />
            <el-table-column
              label="创建时间"
              align="left"
              prop="createTime"
              :formatter="dateFormatter"
              width="180px"
            />
          </el-table>

          <!-- 分页组件 -->
          <Pagination
            v-model:page="addDeviceQueryParams.pageNo"
            v-model:limit="addDeviceQueryParams.pageSize"
            :total="addDeviceTotal"
            @pagination="handlePagination"
          />
        </el-col>
      </el-row>
      <template #footer>
        <el-button type="primary" @click="handleAddDeviceConfirm">确 定</el-button>
        <el-button @click="addDeviceDialogVisible = false">取 消</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script lang="ts" setup>
import { DeviceApi, DeviceVO } from '@/api/mqtt/device'
import { RoleDeviceApi, RoleDeviceVO } from '@/api/system/roledevice'
import { dateFormatter } from '@/utils/formatTime'
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { Icon } from '@/components/Icon'
import Pagination from '@/components/Pagination/index.vue'
import { ref, reactive, nextTick, defineEmits, defineExpose, computed, watch } from 'vue'
import { useI18n } from '@/hooks/web/useI18n'
import { useMessage } from '@/hooks/web/useMessage'

const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗

const dialogVisible = ref(false)
const roleId = ref<number>(0)
// 已分配的设备列表
const assignedDeviceList = ref<DeviceVO[]>([])
// 过滤后的已分配设备列表
const filteredAssignedDeviceList = ref<DeviceVO[]>([])
// 分页后的已分配设备列表
const paginatedAssignedDeviceList = ref<DeviceVO[]>([])
// 已关联设备分页参数
const devicePagination = reactive({
  pageNo: 1,
  pageSize: 10
})
// 当前选中的设备
const selectedDevices = ref<any[]>([])
// 计算属性：是否有选中的设备
const hasSelectedDevices = computed(() => selectedDevices.value.length > 0)

// 主表格相关
const loading = ref(true) // 列表的加载中
const deviceTableRef = ref() // 设备表格引用

// 已关联设备搜索相关
const deviceQueryParams = reactive({
  deviceType: undefined,
  deviceName: undefined,
  serialNumber: undefined
})
const deviceQueryFormRef = ref() // 已关联设备搜索的表单

// 新增设备对话框相关
const addDeviceDialogVisible = ref(false)
const addDeviceLoading = ref(false)
const addDeviceList = ref<DeviceVO[]>([]) // 所有设备列表
const addDeviceSelectedDevices = ref<any[]>([]) // 新增设备对话框中选中的设备
const addDeviceTableRef = ref() // 新增设备表格引用
const addDeviceQueryParams = reactive({
  pageNo: 1,
  pageSize: 10,
  deviceType: undefined,
  deviceName: undefined,
  serialNumber: undefined
})
const addDeviceTotal = ref(0) // 设备总数
const addDeviceQueryFormRef = ref() // 新增设备搜索的表单

const uploadUrl = import.meta.env.VITE_BASE_URL + '/cert/'
const defaultImage = 'https://cube.elemecdn.com/e/fd/0fc7d20532fdaf769a25683617711png.png' // 默认图片
/** 更新分页后的设备列表 */
const updatePaginatedDeviceList = () => {
  const { pageNo, pageSize } = devicePagination
  const start = (pageNo - 1) * pageSize
  const end = start + pageSize
  paginatedAssignedDeviceList.value = filteredAssignedDeviceList.value.slice(start, end)
}

// 监听已分配设备列表变化，更新过滤后的列表
watch(
  assignedDeviceList,
  (newVal) => {
    filteredAssignedDeviceList.value = [...newVal]
  },
  { immediate: true }
)
watch(assignedDeviceList, (newVal) => {
  filteredAssignedDeviceList.value = [...newVal]
  updatePaginatedDeviceList()
}, { immediate: true })

// 监听过滤后的设备列表变化，更新分页后的列表
watch(filteredAssignedDeviceList, () => {
  devicePagination.pageNo = 1 // 重置为第一页
  updatePaginatedDeviceList()
})

// 监听分页参数变化，更新分页后的列表
watch(devicePagination, () => {
  updatePaginatedDeviceList()
}, { deep: true })

/** 打开弹窗 */
const open = async (row: any) => {
  dialogVisible.value = true
  roleId.value = row.id
  // 重置分页参数
  devicePagination.pageNo = 1
  // 加载已分配的设备
  await loadAssignedDevices()
}
const loadDevicesCommon = async (options) => {
  const { isAssigned, queryParams, setLoading, onSuccess } = options
  
  setLoading(true)
  try {
    // 获取已分配设备的逻辑 - 保留原有实现
    // 分页查询角色已分配的设备
    let pageNo = 1
    const pageSize = 100 // 最大页面大小为100
    let allDeviceIds = []
    let hasMore = true

    // 分页获取所有已关联的设备ID
    while (hasMore) {
      const params = {
        roleId: roleId.value,
        pageNo: pageNo,
        pageSize: pageSize,
      }
      const response = await RoleDeviceApi.getRoleDevicePage(params)
      const deviceIds = response.list.map((item) => item.deviceId)
      allDeviceIds = [...allDeviceIds, ...deviceIds]

      // 判断是否还有更多数据
      if (response.list.length < pageSize) {
        hasMore = false
      } else {
        pageNo++
      }
    }

    // 获取设备详细信息
    if (allDeviceIds.length > 0) {
      // 由于可能设备数量较多，需要分批次查询
      const batchSize = 50 // 每批次查询的设备数量
      let allDevices = []
      let total = 0
      for (let i = 0; i < allDeviceIds.length; i += batchSize) {
        const batchIds = allDeviceIds.slice(i, i + batchSize)
        const deviceResponse = await DeviceApi.getDevicePage({
          ids: batchIds.join(','),
          pageNo: 1,
          pageSize: batchIds.length,
          ...queryParams,
          excludeAssigned: isAssigned
        })
        allDevices = [...allDevices, ...deviceResponse.list]
        total = deviceResponse.total
      }

      onSuccess(allDevices, total)
    } else {
      // 修复：当没有已分配设备且查询的是可用设备时，应该查询所有可用设备
      if (isAssigned) {
        // 查询所有可用设备
        const deviceResponse = await DeviceApi.getDevicePage({
          pageNo: queryParams.pageNo || 1,
          pageSize: queryParams.pageSize || 10,
          ...queryParams,
          excludeAssigned: isAssigned
        })
        onSuccess(deviceResponse.list, deviceResponse.total)
      } else {
        // 如果是查询已分配设备，且没有已分配设备，则返回空数组
        onSuccess([], 0)
      }
    }
  } catch (error) {
    message.error(`加载${isAssigned ? '已分配' : '可用'}设备失败: ${error.message}`)
  } finally {
    setLoading(false)
  }
}


/** 加载已分配的设备 */
const loadAssignedDevices = async () => {
  await loadDevicesCommon({
    isAssigned: false, // 获取已分配设备
    queryParams: {
      deviceType: deviceQueryParams.deviceType,
      deviceName: deviceQueryParams.deviceName,
      serialNumber: deviceQueryParams.serialNumber
    },
    setLoading: (value) => {
      loading.value = value
    },
    onSuccess: (devices,total) => {
      assignedDeviceList.value = devices
      // 初始化过滤后的列表
      filteredAssignedDeviceList.value = [...devices]
    }
  })
}

/** 加载所有未关联的设备 */
const loadAllDevices = async () => {
  await loadDevicesCommon({
    isAssigned: true, // 获取未分配设备
    queryParams: {
      pageNo: addDeviceQueryParams.pageNo,
      pageSize: addDeviceQueryParams.pageSize,
      deviceType: addDeviceQueryParams.deviceType,
      deviceName: addDeviceQueryParams.deviceName,
      serialNumber: addDeviceQueryParams.serialNumber
    },
    setLoading: (value) => {
      addDeviceLoading.value = value
    },
    onSuccess: (data,total) => {
      addDeviceList.value = data
      addDeviceTotal.value = total
    }
  })
}


/** 已关联设备搜索按钮操作 */
const handleDeviceQuery = () => {
  // 在前端过滤已关联设备列表
  filteredAssignedDeviceList.value = assignedDeviceList.value.filter((device) => {
    // 设备类型过滤
    if (
      deviceQueryParams.deviceType !== undefined &&
      device.deviceType !== deviceQueryParams.deviceType
    ) {
      return false
    }

    // 设备名称过滤
    if (
      deviceQueryParams.deviceName &&
      !device.deviceName.toLowerCase().includes(deviceQueryParams.deviceName.toLowerCase())
    ) {
      return false
    }

    // 设备序列号过滤
    if (
      deviceQueryParams.serialNumber &&
      (!device.serialNumber ||
        !device.serialNumber.toLowerCase().includes(deviceQueryParams.serialNumber.toLowerCase()))
    ) {
      return false
    }

    return true
  })

  // 重置分页到第一页
  devicePagination.pageNo = 1
}

/** 已关联设备重置按钮操作 */
const resetDeviceQuery = () => {
  // 重置表单字段
  deviceQueryFormRef.value.resetFields()
  // 清空查询参数
  deviceQueryParams.deviceType = undefined
  deviceQueryParams.deviceName = undefined
  deviceQueryParams.serialNumber = undefined
  // 重置过滤后的列表为原始列表
  filteredAssignedDeviceList.value = [...assignedDeviceList.value]
  // 重置分页到第一页
  devicePagination.pageNo = 1
}

/** 移除设备 */
const handleRemoveDevice = async (deviceId: number) => {
  try {
    // 二次确认
    await message.confirm('确定要移除该设备吗？')

    // 查找要删除的关联记录ID
    const params = {
      roleId: roleId.value,
      deviceId: deviceId
    }
    const response = await RoleDeviceApi.getRoleDevicePage(params)

    if (response.list && response.list.length > 0) {
      // 删除设备关联 - 使用正确的请求体格式
      const roleDeviceId = response.list[0].id
      await RoleDeviceApi.deleteRoleDevice({ id: roleDeviceId })

      // 从已分配列表中移除
      assignedDeviceList.value = assignedDeviceList.value.filter((device) => device.id !== deviceId)
      // 同时更新过滤后的列表
      filteredAssignedDeviceList.value = filteredAssignedDeviceList.value.filter(
        (device) => device.id !== deviceId
      )
      message.success('移除成功')
    } else {
      message.error('未找到设备关联记录')
    }
  } catch (error: any) {
    if (error !== 'cancel') {
      // 忽略用户取消操作
      message.error('移除失败: ' + error.message)
    }
  }
}


/** 新增设备按钮点击 */
const handleAddDevice = async () => {
  // 重置查询参数
  addDeviceQueryParams.deviceType = undefined
  addDeviceQueryParams.deviceName = undefined
  addDeviceQueryParams.serialNumber = undefined
  addDeviceQueryParams.pageNo = 1

  // 打开对话框
  addDeviceDialogVisible.value = true

  // 加载未关联的设备
  await loadAllDevices()
}

/** 新增设备搜索按钮操作 */
const handleAddDeviceQuery = () => {
  // 使用查询参数加载设备列表
  loadAllDevices()
}

/** 新增设备重置按钮操作 */
const resetAddDeviceQuery = () => {
  // 重置表单字段
  addDeviceQueryFormRef.value.resetFields()
  // 清空查询参数
  addDeviceQueryParams.deviceType = undefined
  addDeviceQueryParams.deviceName = undefined
  addDeviceQueryParams.serialNumber = undefined
  // 重置分页参数
  addDeviceQueryParams.pageNo = 1
  // 重新加载设备列表
  loadAllDevices()
}

/** 处理新增设备分页变化 */
const handlePagination = ({ page, limit }: { page: number; limit: number }) => {
  addDeviceQueryParams.pageNo = page
  addDeviceQueryParams.pageSize = limit
  loadAllDevices()
}

/** 处理已关联设备分页变化 */
const handleDevicePagination = ({ page, limit }: { page: number; limit: number }) => {
  devicePagination.pageNo = page
  devicePagination.pageSize = limit
  updatePaginatedDeviceList()
}


/** 设备选择变化处理 */
const handleDeviceSelectionChange = (selection: any[]) => {
  selectedDevices.value = selection
}

/** 新增设备选中状态改变 */
const handleAddDeviceSelectionChange = (selection: any[]) => {
  addDeviceSelectedDevices.value = selection
}

/** 批量移除设备 */
const handleBatchRemove = async () => {
  if (selectedDevices.value.length === 0) {
    message.warning('请至少选择一个设备')
    return
  }

  try {
    // 二次确认
    await message.confirm(`确定要移除选中的 ${selectedDevices.value.length} 个设备吗？`)

    // 显示加载状态
    loading.value = true
    
    // 获取要删除的设备ID列表
    const deviceIds = selectedDevices.value.map((device) => device.id)
    
    // 查找这些设备对应的角色设备关联ID
    const roleDeviceIds = []
    for (const deviceId of deviceIds) {
      // 查找要删除的关联记录ID
      const params = {
        roleId: roleId.value,
        deviceId: deviceId
      }
      const response = await RoleDeviceApi.getRoleDevicePage(params)
      if (response.list && response.list.length > 0) {
        roleDeviceIds.push(response.list[0].id)
      }
    }
    
    if (roleDeviceIds.length === 0) {
      message.warning('未找到可删除的设备关联记录')
      return
    }
    
    // 批量删除设备关联 - 使用关联ID而不是设备ID
    const response = await RoleDeviceApi.deleteRoleDeviceBatch(roleDeviceIds)
    console.log('批量删除设备关联', response)
    message.success(`成功移除${roleDeviceIds.length}个设备`)

    // 从已分配列表中移除
    assignedDeviceList.value = assignedDeviceList.value.filter(
      (device) => !deviceIds.includes(device.id)
    )
    // 同时更新过滤后的列表
    filteredAssignedDeviceList.value = filteredAssignedDeviceList.value.filter(
      (device) => !deviceIds.includes(device.id)
    )

    // 清空选中状态
    if (deviceTableRef.value && deviceTableRef.value.clearSelection) {
      deviceTableRef.value.clearSelection()
    }
  } catch (error: any) {
    if (error !== 'cancel') {
      // 忽略用户取消操作
      message.error('批量移除失败: ' + error.message)
    }
  } finally {
    loading.value = false
  }
}


/** 新增设备确认 */
const handleAddDeviceConfirm = async () => {
  try {
    if (addDeviceSelectedDevices.value.length === 0) {
      message.warning('请至少选择一个设备')
      return
    }

    // 显示加载状态
    loading.value = true

    // 将选中的设备添加到已分配列表
    const addedCount = addDeviceSelectedDevices.value.length
    const selectedDevices = [...addDeviceSelectedDevices.value]

    // 获取当前已分配设备的ID集合
    const currentDeviceIds = new Set(assignedDeviceList.value.map((device) => device.id))

    // 获取所有已关联的设备记录
    let pageNo = 1
    const pageSize = 100 // 最大页面大小为100
    let allExistingItems: any[] = []
    let hasMore = true

    // 分页获取所有已关联的设备记录
    while (hasMore) {
      const params = {
        roleId: roleId.value,
        pageNo: pageNo,
        pageSize: pageSize
      }
      const response = await RoleDeviceApi.getRoleDevicePage(params)
      allExistingItems = [...allExistingItems, ...response.list]

      // 判断是否还有更多数据
      if (response.list.length < pageSize) {
        hasMore = false
      } else {
        pageNo++
      }
    }

    // 找出需要新增的设备ID
    const existingDeviceIds = new Set(allExistingItems.map((item: any) => item.deviceId))
    const toAddDevices = selectedDevices.filter((device) => !existingDeviceIds.has(device.id))

    // 批量创建新的关联
    if (toAddDevices.length > 0) {
      // 创建角色设备关联数组
      const createDataList = toAddDevices.map((device) => ({
        id: undefined, // 新建时ID为undefined
        roleId: roleId.value,
        deviceId: device.id
      }))

      // 批量保存设备权限
      await RoleDeviceApi.createRoleDevice(createDataList)
    }

    // 更新已分配列表
    assignedDeviceList.value = [...assignedDeviceList.value, ...selectedDevices]
    // 同时更新过滤后的列表
    filteredAssignedDeviceList.value = [...filteredAssignedDeviceList.value, ...selectedDevices]

    // 关闭新增设备对话框
    addDeviceDialogVisible.value = false

    // 清空选中状态
    addDeviceSelectedDevices.value = []

    message.success(`成功添加并保存${addedCount}个设备`)

    // 通知父组件刷新
    emit('success')
  } catch (error: any) {
    message.error('添加失败: ' + error.message)
  } finally {
    loading.value = false
  }
}

/** 关闭弹窗 */
const handleClose = () => {
  dialogVisible.value = false
}

/** 提交按钮 - 只处理关闭操作 */
const handleSubmit = () => {
  handleClose()
}

// 定义 emit 事件
const emit = defineEmits(['success'])

defineExpose({ open })
</script>

<style scoped>
/* 图片样式限制，避免原始图片过大导致预览异常 */
.device-image {
  width: 40px; /* 固定表格中图片的宽高 */
  height: 40px;
  object-fit: cover; /* 保持图片比例，避免拉伸 */
}
</style>
